#include <xp/net/sttp.h>
#include <xp/net/socket.h>
#include <xp/bas/memory.h>
#include <xp/bas/locale.h>
#include <xp/bas/stdlib.h>
#include <xp/bas/stdio.h>
#include <xp/bas/errno.h>
#include <xp/bas/signal.h>
#include <xp/bas/endian.h>

#ifdef __linux
	#include <mcheck.h>
#endif

int quit = 0;

void set_quit (int sig)
{
	xp_signal (SIGINT, SIG_IGN);
	quit = 1;
	xp_signal (SIGINT, set_quit);
}

int xp_main (int argc, xp_char_t* argv[])
{
	xp_sckhnd_t handle;
	xp_uint16_t port;
	xp_sckadrin4_t to, from;

#ifdef __linux
	mtrace ();
#endif

	xp_setlocale ();
	xp_signal (SIGINT, set_quit);

	if (argc != 2) {
		xp_printf (XP_TEXT("usage: %s port\n"), argv[0]);
		return -1;
	}

	if (xp_sckstartup() == -1) {
		xp_printf (XP_TEXT("can't startup socket subsystem\n"));
		return -1;
	}

	if ((handle = xp_sckopen(PF_INET, SOCK_DGRAM, 0)) == -1) {
		xp_printf (XP_TEXT("can't create socket\n"));
		xp_sckcleanup ();
		return -1;
	}

	XP_STRTOI (port, argv[1], XP_NULL, 10);

	xp_memset (&to, 0, xp_sizeof(to));
	to.sin_family = AF_INET;
	to.sin_port = xp_hton16 (port);

	{
		int n = 1;
		xp_scksetopt (handle, SOL_SOCKET, 
			SO_REUSEADDR, &n, (xp_scklen_t)xp_sizeof(n));
	}

	if (xp_sckbind (handle, 
		(xp_sckadr_t*)&to, (xp_scklen_t)xp_sizeof(to)) == -1) {
		xp_printf (XP_TEXT("can't bind socket\n"));
		xp_sckclose (handle);
		xp_sckcleanup ();
		return -1;
	}

	while (!quit) {
		xp_ssize_t n;
		xp_byte_t buf[65535];
		xp_scklen_t from_len;

		from_len = xp_sizeof(from);
		n = xp_sckrecvfrom (
			handle, buf, xp_sizeof(buf), 0,
			(xp_sckadr_t*)&from, &from_len, 1000);
		if (n == -1) {
			if (xp_geterrno() == XP_ETIMEDOUT) {
				//xp_printf (XP_TEXT("recvfrom timedout. just continuing..\n"));
				continue;
			}
			xp_printf (XP_TEXT("receive_from error: %d\n"), xp_errno);
			break;
		}	

		buf[n] = XP_MCHAR('\0');
#ifdef XP_CHAR_IS_MCHAR
		xp_printf (XP_TEXT("%s"), buf);
#else
		xp_printf (XP_TEXT("%S"), buf);
#endif
		xp_fflush (xp_stdout);

		//xp_scksendto (
		//	handle, buf, n, 0, (xp_sckadr_t*)&from, from_len, -1);
		xp_scksendto (
			handle, "OK xxxxxx", 9, 0, (xp_sckadr_t*)&from, from_len, -1);
	}

	xp_sckclose (handle);
	xp_sckcleanup ();

#ifdef __linux
	muntrace ();
#endif
	return 0;
}

